<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
<meta name="generator" content="Doxygen 1.9.1"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>libconfini: README</title>
<link href="tabs.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="dynsections.js"></script>
<link href="search/search.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="search/searchdata.js"></script>
<script type="text/javascript" src="search/search.js"></script>
<link href="doxygen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea">
<table cellspacing="0" cellpadding="0">
 <tbody>
 <tr style="height: 56px;">
  <td id="projectalign" style="padding-left: 0.5em;">
   <div id="projectname">libconfini
   </div>
   <div id="projectbrief">Yet another INI parser</div>
  </td>
 </tr>
 </tbody>
</table>
</div>
<!-- end header part -->
<!-- Generated by Doxygen 1.9.1 -->
<script type="text/javascript">
/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
var searchBox = new SearchBox("searchBox", "search",false,'Search','.html');
/* @license-end */
</script>
<script type="text/javascript" src="menudata.js"></script>
<script type="text/javascript" src="menu.js"></script>
<script type="text/javascript">
/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
$(function() {
  initMenu('',true,false,'search.php','Search');
  $(document).ready(function() { init_search(); });
});
/* @license-end */</script>
<div id="main-nav"></div>
<!-- window showing the filter options -->
<div id="MSearchSelectWindow"
     onmouseover="return searchBox.OnSearchSelectShow()"
     onmouseout="return searchBox.OnSearchSelectHide()"
     onkeydown="return searchBox.OnSearchSelectKey(event)">
</div>

<!-- iframe showing the search results (closed by default) -->
<div id="MSearchResultsWindow">
<iframe src="javascript:void(0)" frameborder="0" 
        name="MSearchResults" id="MSearchResults">
</iframe>
</div>

</div><!-- top -->
<div class="PageDoc"><div class="header">
  <div class="headertitle">
<div class="title">README </div>  </div>
</div><!--header-->
<div class="contents">
<div class="textblock"><p>Yet another INI parser</p>
<p><a class="anchor" id="md_README"></a></p>
<p><b>libconfini</b> is the ultimate and most consistent INI file parser library written in C. Originally designed for parsing configuration files written by other programs, it focuses on standardization and parsing exactness and is at ease with almost every type of file containing key/value pairs.</p>
<p>The library is fast and suitable for embedded systems. Its algorithms are written from scratch and do not depend on any external library, except for the C standard headers <b>stdio.h</b>, <b>stdlib.h</b>, <b>stdbool.h</b> and <b>stdint.h</b> (and for extreme platforms the code <a class="el" href="baremetal.html">can be also compiled as “bare metal”</a>, with few or no strings attached to the C Standard Library).</p>
<p>Rather than storing the parsed data, <b>libconfini</b> gives the developer the freedom to choose what to do with them through a custom callback invoked for each INI node read. The API has been designed to be powerful, flexible and simple to use.</p>
<p>With <b>libconfini</b> you will find in INI files the same serialization power that you would normally find in other heavily structured formats (such as JSON, YAML, TOML), but with the advantage of using the most human-friendly configuration format ever invented (thanks to their informal status, INI files are indeed more fluid, expressive and human-friendly than formats explicitly designed with the same purpose, such as YAML and TOML). The library's main goal is to be uncommonly powerful in the most tedious and error-prone task when parsing a text file in C: string handling. Thanks to this, the programmer is left free to organize the content parsed as (s)he pleases, assisted by a rich set of fine-tuning tools.</p>
<h1>Features </h1>
<ul>
<li>Typed data support (each value can be parsed as a boolean, a number, a string, an array)</li>
<li>Single/double quotes support in <em>Bash style</em> (i.e. quotes can be opened and closed multiple times within the same value)</li>
<li>Multi-line support</li>
<li>Comment support</li>
<li>Disabled entry support</li>
<li>INI sectioning support (single-level sectioning, as in <code>[foo]</code>; absolute nesting, as in <code>[foo.bar]</code>; relative nesting, as in <code>[.bar]</code>)</li>
<li>Automatic sanitization of values, key names and section paths</li>
<li>Comparison functions designed just for INI source code (capable, for example, to recognize the equality between <code>"Hello world"</code> and <code>"He"l'lo' world</code>, or between <code>foo bar</code> and <code>foo&#160;&#160;&#160;&#160;bar</code>)</li>
<li>Callback pattern</li>
<li>Thread-safety (each parsing process is fully reentrant)</li>
<li>Highly optimized code (single memory allocation for each parsing, heuristic programming, optimization flags)</li>
<li>Function modularity (each public function is independent from all other public functions)</li>
<li>K.I.S.S. (no public functions are automatically invoked during the parsing &ndash; for example, not even single/double quotes are automatically removed from values unless the developer explicitly decides to use the formatting functions provided by the API)</li>
<li>Robust and cross-platform file access (UTF-8 support; protection against null byte injection; support of all code representations of new lines &ndash; i.e. ubiquitous support of Classic Mac OS' <code>CR</code>, Unix' <code>LF</code>, Windows' <code>CR</code>+<code>LF</code>, RISC OS Open's <code>LF</code>+<code>CR</code>)</li>
</ul>
<h1>Sample usage </h1>
<p>log.ini:</p>
<div class="fragment"><div class="line">[users]</div>
<div class="line">have_visited = ronnie, lilly82, robrob</div>
<div class="line"> </div>
<div class="line">[last_update]</div>
<div class="line">date = 12.03.2017</div>
</div><!-- fragment --><p>example.c:</p>
<div class="fragment"><div class="line"><span class="preprocessor">#include &lt;<a class="code" href="confini_8h.html">confini.h</a>&gt;</span></div>
<div class="line"> </div>
<div class="line"><span class="keyword">static</span> <span class="keywordtype">int</span> callback (<a class="code" href="structIniDispatch.html">IniDispatch</a> * disp, <span class="keywordtype">void</span> * v_other) {</div>
<div class="line"> </div>
<div class="line"><span class="preprocessor">  #define IS_KEY(SECTION, KEY) \</span></div>
<div class="line"><span class="preprocessor">    (ini_array_match(SECTION, disp-&gt;append_to, &#39;.&#39;, disp-&gt;format) &amp;&amp; \</span></div>
<div class="line"><span class="preprocessor">    ini_string_match_ii(KEY, disp-&gt;data, disp-&gt;format))</span></div>
<div class="line"> </div>
<div class="line">  <span class="keywordflow">if</span> (disp-&gt;<a class="code" href="structIniDispatch.html#a7f6ebc6713aae413c4157ce68008a8a8">type</a> == <a class="code" href="confini_8h.html#a4e394db479f56eaa830ade09c907461ba97333d01dfff8f9a9c690fc559751b45">INI_KEY</a>) {</div>
<div class="line"> </div>
<div class="line">    <span class="keywordflow">if</span> (IS_KEY(<span class="stringliteral">&quot;users&quot;</span>, <span class="stringliteral">&quot;have_visited&quot;</span>)) {</div>
<div class="line"> </div>
<div class="line">      <span class="comment">/* No need to parse this field as an array right now */</span></div>
<div class="line">      printf(<span class="stringliteral">&quot;People who have visited: %s\n&quot;</span>, disp-&gt;<a class="code" href="structIniDispatch.html#a8d7eb3387ff5ecb79900fae717234d16">value</a>);</div>
<div class="line"> </div>
<div class="line">    } <span class="keywordflow">else</span> <span class="keywordflow">if</span> (IS_KEY(<span class="stringliteral">&quot;last_update&quot;</span>, <span class="stringliteral">&quot;date&quot;</span>)) {</div>
<div class="line"> </div>
<div class="line">      printf(<span class="stringliteral">&quot;Last update: %s\n&quot;</span>, disp-&gt;<a class="code" href="structIniDispatch.html#a8d7eb3387ff5ecb79900fae717234d16">value</a>);</div>
<div class="line"> </div>
<div class="line">    }</div>
<div class="line"> </div>
<div class="line">  }</div>
<div class="line"> </div>
<div class="line"><span class="preprocessor">  #undef IS_KEY</span></div>
<div class="line"> </div>
<div class="line">  <span class="keywordflow">return</span> 0;</div>
<div class="line"> </div>
<div class="line">}</div>
<div class="line"> </div>
<div class="line"><span class="keywordtype">int</span> main () {</div>
<div class="line"> </div>
<div class="line">  <span class="keywordflow">if</span> (<a class="code" href="confini_8h.html#a54be108d26619db3066ce1c000dc8a17">load_ini_path</a>(<span class="stringliteral">&quot;log.ini&quot;</span>, <a class="code" href="confini_8h.html#aafa50d590c715f37b74fa5938a35a56f">INI_DEFAULT_FORMAT</a>, NULL, callback, NULL)) {</div>
<div class="line"> </div>
<div class="line">    fprintf(stderr, <span class="stringliteral">&quot;Sorry, something went wrong :-(\n&quot;</span>);</div>
<div class="line">    <span class="keywordflow">return</span> 1;</div>
<div class="line"> </div>
<div class="line">  }</div>
<div class="line"> </div>
<div class="line">  <span class="keywordflow">return</span> 0;</div>
<div class="line"> </div>
<div class="line">}</div>
<div class="ttc" id="aconfini_8h_html"><div class="ttname"><a href="confini_8h.html">confini.h</a></div><div class="ttdoc">libconfini header</div></div>
<div class="ttc" id="aconfini_8h_html_a4e394db479f56eaa830ade09c907461ba97333d01dfff8f9a9c690fc559751b45"><div class="ttname"><a href="confini_8h.html#a4e394db479f56eaa830ade09c907461ba97333d01dfff8f9a9c690fc559751b45">INI_KEY</a></div><div class="ttdeci">@ INI_KEY</div><div class="ttdef"><b>Definition:</b> confini.h:442</div></div>
<div class="ttc" id="aconfini_8h_html_a54be108d26619db3066ce1c000dc8a17"><div class="ttname"><a href="confini_8h.html#a54be108d26619db3066ce1c000dc8a17">load_ini_path</a></div><div class="ttdeci">int load_ini_path(const char *const path, const IniFormat format, const IniStatsHandler f_init, const IniDispHandler f_foreach, void *const user_data)</div><div class="ttdoc">Parse an INI file and dispatch its content to a custom callback using a path as argument.</div><div class="ttdef"><b>Definition:</b> confini.c:3274</div></div>
<div class="ttc" id="aconfini_8h_html_aafa50d590c715f37b74fa5938a35a56f"><div class="ttname"><a href="confini_8h.html#aafa50d590c715f37b74fa5938a35a56f">INI_DEFAULT_FORMAT</a></div><div class="ttdeci">static const IniFormat INI_DEFAULT_FORMAT</div><div class="ttdoc">A model format for standard INI files.</div><div class="ttdef"><b>Definition:</b> confini.h:524</div></div>
<div class="ttc" id="astructIniDispatch_html"><div class="ttname"><a href="structIniDispatch.html">IniDispatch</a></div><div class="ttdoc">Dispatch of a single INI node.</div><div class="ttdef"><b>Definition:</b> confini.h:131</div></div>
<div class="ttc" id="astructIniDispatch_html_a7f6ebc6713aae413c4157ce68008a8a8"><div class="ttname"><a href="structIniDispatch.html#a7f6ebc6713aae413c4157ce68008a8a8">IniDispatch::type</a></div><div class="ttdeci">uint_least8_t type</div><div class="ttdef"><b>Definition:</b> confini.h:133</div></div>
<div class="ttc" id="astructIniDispatch_html_a8d7eb3387ff5ecb79900fae717234d16"><div class="ttname"><a href="structIniDispatch.html#a8d7eb3387ff5ecb79900fae717234d16">IniDispatch::value</a></div><div class="ttdeci">char * value</div><div class="ttdef"><b>Definition:</b> confini.h:135</div></div>
</div><!-- fragment --><p>Output:</p>
<div class="fragment"><div class="line">People who have visited: ronnie, lilly82, robrob</div>
<div class="line">Last update: 12.03.2017</div>
</div><!-- fragment --><p>If you are using C++, under <code>examples/cplusplus/map.cpp</code> you can find a snippet for storing an INI file into a class that relies on a <code>std::unordered_map</code> object.</p>
<p>For more details, please read the <a class="el" href="libconfini.html">Library Functions Manual</a> (<code>man libconfini</code>) &ndash; a standalone HTML version is available <a class="el" href="install.html">here</a> &ndash; and the manual of the header file (<code>man <a class="el" href="confini_8h.html" title="libconfini header">confini.h</a></code>). The code is available on <a href="https://github.com/">GitHub</a> under <a href="https://github.com/madmurphy/libconfini">madmurphy/libconfini</a>).</p>
<h1>Installation </h1>
<p>Despite the small footprint, <b>libconfini</b> has been conceived as a shared library (but it can be used as a static library as well). An automatic list of the distributions that ship the library already compiled is available <a href="https://repology.org/project/libconfini/versions">here</a>.</p>
<p>If a pre-compiled package for your platform is not available, on most Unix-like systems it is possible to install <b>libconfini</b> using the following common steps:</p>
<div class="fragment"><div class="line">./configure</div>
<div class="line">make</div>
<div class="line">make install-strip</div>
</div><!-- fragment --><p>If the <code>strip</code> utility is not available on your machine, use <code>make install</code> instead (it will produce larger binaries)</p>
<p>For a minimum installation without development files (i.e. static libraries, headers, documentation, examples, etc.) use <code>./configure --disable-devel</code>.</p>
<p>If the <code>configure</code> script is missing you need to generate it by running the <code>bootstrap</code> script. By default, <code>bootstrap</code> will also run the <code>configure</code> script immediately after having generated it, so you may type the <code>make</code> command directly after <code>bootstrap</code>. To list different options use <code>./bootstrap --help</code>.</p>
<p>If you are using <b>Microsoft Windows</b>, a batch script for compiling <b>libconfini</b> with <a href="http://www.mingw.org/"><b>MinGW</b></a> without <b>Bash</b> is available (<code>mgwmake.bat</code>). If you are interested in using <b>GNU Make</b> for compiling <b>libconfini</b>, you can integrate <b>MinGW</b> with <a href="http://www.mingw.org/wiki/MSYS"><b>MSYS</b></a>, or you can directly use <a href="https://www.msys2.org/"><b>MSYS2</b></a> and <a href="https://packages.msys2.org/base/mingw-w64-libconfini">its official port</a> of the library. Alternatively, <a href="https://github.com/fd00/yacp/tree/master/libconfini">an unofficial port</a> of <b>libconfini</b> for <a href="https://www.cygwin.com/"><b>Cygwin</b></a> is available.</p>
<p>For further information, see <a class="el" href="install.html">INSTALL</a>.</p>
<h1>Bindings </h1>
<p><a href="https://danyspin97.org/">Danilo Spinella</a> maintains <a href="https://github.com/DanySpin97/libconfini-d">a D binding package</a> of <b>libconfini</b>.</p>
<h1>Free software </h1>
<p>This library is free software. You can redistribute it and/or modify it under the terms of the GPL license version 3 or any later version. See <a href="https://github.com/madmurphy/libconfini/blob/master/COPYING">COPYING</a> for details. </p>
</div></div><!-- contents -->
</div><!-- PageDoc -->
<!-- start footer part -->
<hr class="footer"/><address class="footer"><small>
Generated by&#160;<a href="https://www.doxygen.org/index.html"><img class="footer" src="doxygen.svg" width="104" height="31" alt="doxygen"/></a> 1.9.1
</small></address>
</body>
</html>
